#include "ImageDrawable.h"
#include "include/core/SkCanvas.h"
#include "include/core/SkBitmap.h"
#include "include/core/SkImage.h"
#include "include/core/SkSurface.h"
#include "include/core/SkData.h"
#include "include/codec/SkCodec.h"
#include "lang/Math.h"
using namespace yzrilyzr_lang;
namespace yzrilyzr_simplecanvas{
	ImageDrawable::ImageDrawable(const std::string & filePath){
		image=SkImages::DeferredFromEncodedData(SkData::MakeFromFileName(filePath.c_str()));
	}
	void ImageDrawable::draw(SkCanvas & canvas){
		if(image == nullptr)return;
		SkPaint p;
		Rect & b=getBounds();
		int32_t iW=getIntrinsicWidth();
		int32_t iH=getIntrinsicHeight();

		switch(mode){
			case ImageScaleMode::NONE:
				canvas.drawImageRect(image, SkRect::MakeXYWH(b.left, b.top, iW, iH),
									 SkSamplingOptions::Aniso(2), &p);
				break;
			case ImageScaleMode::FIT_XY:
				canvas.drawImageRect(image, SkRect::MakeLTRB(b.left, b.top, b.right, b.bottom), SkSamplingOptions::Aniso(2), &p);
				break;

			case ImageScaleMode::FIT_START:
			case ImageScaleMode::FIT_CENTER:
			case ImageScaleMode::FIT_END:
			{
				float scale=Math::min((float)b.width() / iW, (float)b.height() / iH);
				float scaledW=scale * iW;
				float scaledH=scale * iH;
				float left=b.left;
				float top=b.top;

				if(mode == ImageScaleMode::FIT_CENTER){
					left=b.left + (b.width() - scaledW) / 2;
					top=b.top + (b.height() - scaledH) / 2;
				} else if(mode == ImageScaleMode::FIT_END){
					left=b.right - scaledW;
					top=b.bottom - scaledH;
				}

				canvas.drawImageRect(image, SkRect::MakeLTRB(left, top, left + scaledW, top + scaledH),
									 SkSamplingOptions::Aniso(2), &p);
				break;
			}

			case ImageScaleMode::CENTER:
			{
				float left=(float)b.left + (b.width() - iW) / 2;
				float top=(float)b.top + (b.height() - iH) / 2;
				canvas.drawImageRect(image, SkRect::MakeLTRB(left, top, left + iW, top + iH),
									 SkSamplingOptions::Aniso(2), &p);
				break;
			}

			case ImageScaleMode::CENTER_CROP:
			{
				float scale=Math::max((float)b.width() / iW, (float)b.height() / iH);
				float scaledW=iW * scale;
				float scaledH=iH * scale;
				float left=(float)b.left + (b.width() - scaledW) / 2;
				float top=(float)b.top + (b.height() - scaledH) / 2;

				SkRect srcRect=SkRect::MakeXYWH(
					(scaledW - b.width()) / 2 / scale,
					(scaledH - b.height()) / 2 / scale,
					b.width() / scale,
					b.height() / scale
				);

				canvas.drawImageRect(image, srcRect, SkRect::MakeLTRB(b.left, b.top, b.right, b.bottom), SkSamplingOptions::Aniso(2), &p,
									 SkCanvas::kStrict_SrcRectConstraint);
				break;
			}

			case ImageScaleMode::CENTER_INSIDE:
			{
				float scale=Math::min(1.0f, Math::min((float)b.width() / iW, (float)b.height() / iH));
				float scaledW=iW * scale;
				float scaledH=iH * scale;
				float left=b.left + (b.width() - scaledW) / 2;
				float top=b.top + (b.height() - scaledH) / 2;

				canvas.drawImageRect(image, SkRect::MakeLTRB(left, top, left + scaledW, top + scaledH),
									 SkSamplingOptions::Aniso(2), &p);
				break;
			}
		}
	}int32_t ImageDrawable::getIntrinsicWidth(){
		if(image == nullptr)return NOT_INTRINSIC;
		return image.get()->width();
	}
	int32_t ImageDrawable::getIntrinsicHeight(){
		if(image == nullptr)return NOT_INTRINSIC;
		return image.get()->height();
	}
}